package com.dragon.app.concurrent;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 
 * <p>
 * class: LockConditionTest
 * </p>
 * <p>
 * Description: 测试Lock的Condition。 三个线程A、B、C，线程A打印5次，然后线程B打印10次，然后C打印15次，如此循环10轮。  分析：A线程打印5次可以看作A的一个任务，B、C也相同。
 * </p>
 * 
 * @author SmallDragon
 * @date 2019年5月6日
 *
 */
public class LockConditionTest {

	public static void main(String[] args) {

		Resource resource = new Resource();

		new Thread(() -> {
			for (int i = 1; i <= 10; i++) {
				resource.print5(i);
			}
		}, "Thread-A").start();

		new Thread(() -> {
			for (int i = 1; i <= 10; i++) {
				resource.print10(i);
			}
		}, "Thread-B").start();

		new Thread(() -> {
			for (int i = 1; i <= 10; i++) {
				resource.print15(i);
			}
		}, "Thread-C").start();

	}

	static class Resource {
		private volatile int num = 1;
		Lock lock = new ReentrantLock();
		Condition cd1, cd2, cd3;
		
		{
			cd1 = lock.newCondition();
			cd2 = lock.newCondition();
			cd3 = lock.newCondition();
		}

		public void print5(int order) {
			lock.lock();
			try {
				while (num != 1) {
					System.out.println(Thread.currentThread().getName() + ":wait");
					cd1.await();
				}
				for (int i = 1; i <= 5; i++) {
					System.out.println(Thread.currentThread().getName() + "第" + order + "轮，第" + i + "次 : aaa");
				}
				num = 2;
				cd2.signalAll();
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				lock.unlock();
			}
		}

		public void print10(int order) {
			lock.lock();
			try {
				while (num != 2) {
					System.out.println(Thread.currentThread().getName() + ":wait");
					cd2.await();
				}
				for (int i = 1; i <= 10; i++) {
					System.out.println(Thread.currentThread().getName() + "第" + order + "轮，第" + i + "次 : bbb");
				}
				num = 3;
				cd3.signalAll();
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				lock.unlock();
			}
		}

		public void print15(int order) {
			lock.lock();
			try {
				while (num != 3) {
					System.out.println(Thread.currentThread().getName() + ":wait");
					cd3.await();
				}
				for (int i = 1; i <= 15; i++) {
					System.out.println(Thread.currentThread().getName() + "第" + order + "轮，第" + i + "次 : ccc");
				}
				num = 1;
				cd1.signalAll();
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				lock.unlock();
			}
		}

	}

}
